﻿using System;
using System.Runtime.Serialization;

namespace Loki.Utils
{
    /// <summary>
    /// Represents a weak reference, which references an object while still
    /// allowing that object to be garbage collected.
    /// </summary>
    /// <typeparam name="T">
    /// The type of <see cref="Target"/>.
    /// </typeparam>
    [Serializable]
    public class WeakReference<T> : WeakReference where T : class
    {
        /// <summary>
        /// Creates an new weak reference on the specified target.
        /// </summary>
        /// <param name="P_Target">The Target.</param>
        public static WeakReference<T> Create(T P_Target)
        {
            if (P_Target == null)
            {
                return WeakNullReference<T>.Value;
            }

            return new WeakReference<T>(P_Target);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="WeakReference{T}"/> class,
        /// referencing the specified object.
        /// </summary>
        /// <param name="P_Target">
        /// The object to track or <see langword="null"/>. 
        /// </param>
        protected WeakReference(T P_Target)
            : base(P_Target, false)
        {
        }

        /// <summary>
        /// Gets the object (the target) referenced by the current WeakReference object.
        /// </summary>
        /// <value>The object (the target) referenced by the current WeakReference object.</value>
        public new T Target
        {
            get { return (T)base.Target; }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="WeakReference{T}"/> class,
        /// referencing the specified object and using the specified
        /// resurrection tracking.
        /// </summary>
        /// <param name="P_Target">An object to track. 
        /// </param>
        /// <param name="P_TrackResurrection">Indicates when to stop tracking the
        /// object. If <see langword="true"/>, the object is tracked after
        /// finalization; if <see langword="false"/>, the object is only tracked
        /// until finalization. 
        /// </param>
        protected WeakReference(T P_Target, bool P_TrackResurrection)
            : base(P_Target, P_TrackResurrection)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="WeakReference{T}"/> class,
        /// using deserialized data from the specified serialization and stream
        /// objects.
        /// </summary>
        /// <param name="P_Info">
        /// An object that holds all the data needed to serialize or deserialize
        /// the current <see cref="T:System.WeakReference"/> object. 
        /// </param>
        /// <param name="P_Context">Describes the source and
        /// destination of the serialized stream specified by 
        /// <paramref name="info"/> (Reserved) . 
        /// </param>
        /// <exception cref="ArgumentNullException">The parameter <paramref name="P_Info"/> is 
        /// <see langword="null"/>. 
        /// </exception>
        protected WeakReference(SerializationInfo P_Info, StreamingContext P_Context)
            : base(P_Info, P_Context)
        {
        }
    }
}
